package com.cjk.console.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.cjk.console.enums.EventType;
import com.cjk.console.model.MqttMessage;
import com.cjk.console.model.TunnelResult;
import com.cjk.console.request.DeviceRequest;
import com.cjk.console.tunnel.TunnelConfig;
import com.cjk.console.tunnel.TunnelMng;
import com.cjk.console.tunnel.TunnelSystemShell;
import com.cjk.foundation.commons.BusinessException;
import com.cjk.foundation.commons.response.PageResponse;
import com.cjk.foundation.commons.response.Response;
import com.cjk.foundation.dao.DeviceDao;
import com.cjk.foundation.dao.TunnelDao;
import com.cjk.foundation.entity.DeviceEntity;
import com.cjk.foundation.entity.TunnelEntity;
import com.cjk.foundation.enums.DeviceStatus;
import com.cjk.foundation.enums.TunnelStatus;

@Service
public class TunnelServiceImpl implements TunnelService {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(TunnelServiceImpl.class);

	@Autowired
	private DeviceDao deviceDao;

	@Autowired
	private TunnelDao tunnelDao;

	@Autowired
	private MqttService mqttService;

	@Override
	public Response createTunnel(DeviceRequest request, Integer userId) {
		DeviceEntity deviceEntity = deviceDao.selectBySn(request.getSn(), userId);
		if (deviceEntity == null) {
			throw new BusinessException("设备不存在");
		}
		if (!deviceEntity.getStatus().equals(DeviceStatus.ONLINE)) {
			throw new BusinessException("设备不在线");
		}

		Integer remotePort = 22;
		String remoteHost = "127.0.0.1";
		String service = "ssh";
		switch (request.getTunnelService()) {
		case HTTP:
			remotePort = 80;
			service = "80";
			break;
		case CUSTOM:
			remoteHost = request.getTunnelCustomIp();
			remotePort = request.getTunnelCustomPort();
			service = String.valueOf(request.getTunnelCustomPort());
			break;
		default:
			break;
		}
		TunnelEntity existTunnelEntity = tunnelDao.selectByCondition(request.getSn(), remotePort, TunnelStatus.ESTABLISHED);
		if (existTunnelEntity != null) {
			return Response.success(existTunnelEntity.getId());
		}
		
		// TODO 最大隧道数
		
		// TODO 获取可用端口
		Integer maxPortInUsed = tunnelDao.selectMaxPortInUsed();
		final Integer localPort = maxPortInUsed == null ? 10000 : maxPortInUsed + 1;
		
		String command = TunnelMng.formatCommand(localPort, remoteHost, service);
		if (StringUtils.isBlank(command)) {
			throw new BusinessException("构建命令错误");
		}
		
		TunnelEntity tunnelEntity = new TunnelEntity();
		tunnelEntity.setUserId(userId);
		tunnelEntity.setLocalPort(localPort);
		tunnelEntity.setLocalHost(TunnelConfig.getSshdHost());
		tunnelEntity.setRemoteClient(request.getSn());
		tunnelEntity.setRemoteHost(remoteHost);
		tunnelEntity.setRemoteService(request.getTunnelService());
		tunnelEntity.setRemotePort(remotePort);
		tunnelEntity.setTunnelStatus(TunnelStatus.ASSIGNED);
		tunnelDao.insert(tunnelEntity);


		List<String> commands = new ArrayList<>();
		commands.add(command);

		MqttMessage message = new MqttMessage();
		message.setEventType(EventType.CREATE_TUNNEL);
		message.setSn(request.getSn());
		message.setTunnelId(tunnelEntity.getId());
		message.setCommands(commands);
		mqttService.publish(request.getSn(), message);

		return Response.success(tunnelEntity.getId());
	}

	@Override
	public Response destoryTunnel(Integer tunnelId) {
		TunnelEntity tunnelEntity = tunnelDao.selectById(tunnelId);
		if (!TunnelSystemShell.destoryTunnel(tunnelEntity.getLocalPort())) {
			throw new BusinessException("关闭隧道失败");
		}
		tunnelDao.updateStatus(tunnelId, TunnelStatus.CLOSED);
		return Response.success();
	}

	@Override
	public PageResponse getTunnelList(DeviceRequest request) {
		List<TunnelEntity> tunnelEntities = tunnelDao.selectListByCondition(request.getSn(), null, null, request.getPage(),
				request.getPageSize());
		if (CollectionUtils.isEmpty(tunnelEntities)) {
			return PageResponse.success(0, request.getPageSize(), tunnelEntities);
		}
		final Integer total = tunnelDao.selectCountByCondition(request.getSn(), null, null);
		return PageResponse.success(total, request.getPageSize(), tunnelEntities);
	}

	@Override
	public Response getTunnelStatus(Integer tunnelId) {
		TunnelEntity tunnelEntity = tunnelDao.selectById(tunnelId);
		if (!tunnelEntity.getTunnelStatus().equals(TunnelStatus.ASSIGNED)) {
			return Response.success(tunnelEntity);
		}
		return Response.success(tunnelEntity.getTunnelStatus());
	}

	@Override
	public void createComplete(Integer tunnelId, String line) {
		Date date = new Date();
		TunnelResult result = JSON.parseObject(line, TunnelResult.class);
		LOGGER.info(JSON.toJSONString(result));
		TunnelEntity tunnelEntity = tunnelDao.selectById(tunnelId);
		if (tunnelEntity == null) {
			throw new BusinessException("设备不存在");
		}
		if (result.getCode() == 0) {
			tunnelDao.createComplete(date, TunnelStatus.ESTABLISHED, result.getCode(), result.getMsg(), "true",
					tunnelId);
		} else {
			tunnelDao.createComplete(date, TunnelStatus.CLOSED, result.getCode(), result.getMsg(), "false", tunnelId);
		}
	}

}
